//
//  FMRemotePlayer.m
//  FMRemotePlayer
//
//  Created by appbanana on 2017/3/12.
//  Copyright © 2017年 appbanana. All rights reserved.
//

#import "FMRemotePlayer.h"
#import <AVFoundation/AVFoundation.h>
#import "FMResourceLoader.h"
#import "NSURL+Extension.h"


@interface FMRemotePlayer ()
{
    BOOL _userStop;
}

@property (strong, nonatomic) AVPlayer *player;

@property (nonatomic, strong) FMResourceLoader *loader;



@end

@implementation FMRemotePlayer

static FMRemotePlayer *_shareInstance;

+ (instancetype)shareInstance{
    if (!_shareInstance) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _shareInstance = [[FMRemotePlayer alloc] init];
        });
    }
    return _shareInstance;
}


- (void)playWithUrl:(NSURL *)url isCache:(BOOL)isCache
{
    //容错处理
    if ([self.currentURL isEqual:url]) {
        //这要根据状态值来判断
        if (self.state == FMRemoteAudioPlayerStateLoading) {
            return ;
        }
        if (self.state == FMRemoteAudioPlayerStatePause) {
            [self resume];
            return ;
        }
        if (self.state == FMRemoteAudioPlayerStatePlaying) {
            return ;
        }
        //失败不用管 会自动走下边 重新来获取
    }
    self.currentURL = url;
    if (isCache) {
        url = [url fmURL];
    }
    //如果这不清除观察者 当他正在播放的时候你再次播放的时候回闪退 原因是这个原来的item已经销毁了,但是观察者还在 所有会这样的问题
    if (self.player.currentItem) {
        [self cleanObserverWithItem:self.player.currentItem];
    }
    //资源的请求者
    AVURLAsset *asset = [AVURLAsset assetWithURL:url];
    self.loader = [[FMResourceLoader alloc] init];
    [asset.resourceLoader setDelegate:self.loader queue:dispatch_get_main_queue()];

    //资源的组织者
    AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset];
    //监听状态值 看是否可以播放
    [item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    //监听缓存
    [item addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];
    //播放完成的通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playEnd) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
    //监听是否被中断 比如突然来电话
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playInterrupt) name:AVPlayerItemPlaybackStalledNotification object:nil];

    [self.player pause];
    //资源的播放者
    self.player = [AVPlayer playerWithPlayerItem:item];
}


- (void)pause{
    [self.player pause];
    if (self.player) {
        _userStop = YES;
        self.state = FMRemoteAudioPlayerStatePause;
    }
}


- (void)resume{
    [self.player play];
    if (self.player.rate != 0) {
        _userStop = NO;
        self.state = FMRemoteAudioPlayerStatePlaying;
    }
}


- (void)stop{
    [self.player pause];
    [self cleanObserverWithItem:self.player.currentItem];
    self.player = nil;
    self.state = FMRemoteAudioPlayerStateStopped;
    _userStop = YES;
}

- (void)seekWithTimeInterval:(NSTimeInterval)timeInterval{
    //首先拿到当前时间 加上15s 注意:需要把当前帧换算成秒
    NSTimeInterval sec = CMTimeGetSeconds(self.player.currentTime) + timeInterval;
    
    [self.player seekToTime:CMTimeMakeWithSeconds(sec, NSEC_PER_SEC) completionHandler:^(BOOL finished) {
        if (finished) {
            NSLog(@"确定正在加载这个时间段的资源");
        }else{
            NSLog(@"取消加载这个时间段的资源");

        }
    }];
    
}


- (void)seekToProgress:(float)progress{
    
    NSTimeInterval sec = CMTimeGetSeconds(self.player.currentItem.duration) * progress;
    [self.player seekToTime:CMTimeMakeWithSeconds(sec, NSEC_PER_SEC) completionHandler:^(BOOL finished) {
        if (finished) {
            NSLog(@"确定正在加载这个时间段的资源");
        }else{
            NSLog(@"取消加载这个时间段的资源");
            
        }
    }];


}



- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    if ([keyPath isEqualToString:@"status"]) {
        AVPlayerItemStatus status = [change[NSKeyValueChangeNewKey] unsignedIntegerValue];
        switch (status) {
            case AVPlayerItemStatusUnknown:
            {
                self.state = FMRemoteAudioPlayerStateFailed;
                break;
            }
            case AVPlayerItemStatusReadyToPlay:
            {
//                [self.player play];
                [self resume];
                break;
            }
            case AVPlayerItemStatusFailed:
            {
                self.state = FMRemoteAudioPlayerStateFailed;
                break;
            }
                
            default:
                break;
        }
    }
    
    if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) {
        //缓存进度
        BOOL playbackLikelyToKeepUp = [change[NSKeyValueChangeNewKey] boolValue];
        if (playbackLikelyToKeepUp) {
            NSLog(@"缓存完成 可以进行播放");
            //用户的点击的优先级高 当你缓存完成 但用户已经点击了暂停 那就不能播放
            if (!_userStop) {
                [self resume];
            }
        }else{
            self.state = FMRemoteAudioPlayerStateLoading;
        }
    }
}

- (void)playEnd{
    NSLog(@"播放完成");
    self.state = FMRemoteAudioPlayerStateStopped;
    if (self.playEndBlock) {
        self.playEndBlock();
    }
    
}

- (void)playInterrupt{
    self.state = FMRemoteAudioPlayerStatePause;

    
}

- (void)cleanObserverWithItem:(AVPlayerItem *)item{
    [item removeObserver:self forKeyPath:@"status"];
    [item removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark-------seter getter

- (void)setRate:(float)rate{
    _rate = rate;
    self.player.rate = rate;
}

- (void)setMuted:(BOOL)muted{
    _muted = muted;
    self.player.muted = muted;
}

- (void)setVolume:(float)volume{
    if (volume > 0) {
        self.muted = NO;
    }
    self.player.volume = volume;
}

- (float)volume{
    return self.player.volume;
}

- (NSTimeInterval)currentTime{
    NSTimeInterval currentTime = CMTimeGetSeconds(self.player.currentTime);
    if (isnan(currentTime)) {
        return 0;
    }
    return currentTime;
}

- (NSTimeInterval)duration{
    NSTimeInterval totalTime = CMTimeGetSeconds(self.player.currentItem.duration);
    if (isnan(totalTime)) {
        return 0;
    }
    return totalTime;
}

- (float)progress{
    NSTimeInterval currentTime = [self currentTime];
    NSTimeInterval duration = [self duration];
    if (duration == 0) {
        return 0;
    }
    return currentTime * 1.0 / duration;
}

- (float)loadProgress{
    if (self.duration == 0) {
        return 0;
    }
    CMTimeRange range = [self.player.currentItem.loadedTimeRanges.lastObject CMTimeRangeValue];
    CMTime loadTime = CMTimeAdd(range.start, range.duration);
    NSTimeInterval loadTimeSec = CMTimeGetSeconds(loadTime);
    return (1.0 * loadTimeSec / [self duration]);
}

- (void)setState:(FMRemoteAudioPlayerState)state{
    _state = state;
    if (self.stateChangeBlock) {
        self.stateChangeBlock(state);
    }
    if (self.currentURL) {
        [[NSNotificationCenter defaultCenter] postNotificationName:kRemotePlayerURLOrStateChangeNotification object:nil userInfo:@{@"playURL" : self.currentURL, @"playState" : @(self.state)}];
    }
}

- (void)setCurrentURL:(NSURL *)currentURL{
    _currentURL = currentURL;
    if (self.currentURL) {
        [[NSNotificationCenter defaultCenter] postNotificationName:kRemotePlayerURLOrStateChangeNotification object:nil userInfo:@{@"playURL" : self.currentURL, @"playState" : @(self.state)}];
    }
}



@end
